package com.dream.filter;

import com.dream.entity.JwtUser;
import com.dream.entity.ResponseResult;
import com.dream.util.JwtTokenUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;


/**
 * 登录接口”/login"两种拦截方式
 * 1. 继承UsernamePasswordAuthenticationFilter，重写attemptAuthentication（）方法
 * 2. 建立一个controller, 路径为/login. 且为post请求
 */
@Slf4j
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super.setFilterProcessesUrl("/login");
        this.authenticationManager = authenticationManager;
    }

    @SneakyThrows
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //从request中获取用户名密码

        //查询数据库验证，用户名密码是否正确，验证用户是否过期、是否被锁定等等信息，验证不成功使用response输出登录失败信息且返回null

        //验证成功:根据用户名密码生成UsernamePasswordAuthenticationToken，并且authenticated字段设置为true
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("admin", "admin", new ArrayList<>());
        //通过Provider调用authenticate方法，默认是走DaoAuthenticationProvider
        //走哪个Provider的authenticate方法是根据Provide中的supports确定的
        return authenticationManager.authenticate(token);
    }

    /**
     * 重写登录成功方法
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //获取当前登录成功用户
        JwtUser jwtUser = (JwtUser)authResult.getPrincipal();

        //创建token
        String token = JwtTokenUtils.createToken(jwtUser.getUsername(), jwtUser.getPassword());
        //保存到redis中

        //响应
        JwtTokenUtils.writeResponse(response,token, ResponseResult.success("登录成功"));
    }

    /**
     * 重写登录失败方法
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        //获取失败原因
        String message = failed.getMessage();

        //更新用户信息，如根据登录失败次数跟新禁用状态等等信息（登录次数可以放在redis中）

        //返回登录失败信息
        JwtTokenUtils.writeResponse(response,null, ResponseResult.fail("登录失败"));
    }
}
